home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 May: Tool Chest / Developer CD Series May 1996 (Tool Chest) (Apple Computer) (1996).iso / Sample Code / SCSI Samples 1.0 / SCSI Simple Sample 06⁄15 ƒ / Src / DoListSCSIDevices.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-06-16  |  6.4 KB  |  163 lines  |  [TEXT/KAHL]

  1. /*                                DoListSCSIDevices.c                                */
  2. /*
  3.  * DoListSCSIDevices.c
  4.  * Copyright © 1992-94 Apple Computer Inc. All Rights Reserved.
  5.  *
  6.  * Find all SCSI devices. The alogrithm first asks the SCSI Manager for the
  7.  * number of busses, then loops through each bus for each device and LUN.
  8.  * old SCSI Manager. This is made complex by the flexible SCSI Manager 4.3
  9.  * architecture: it is possible for the asynchronous SCSI Manager to only
  10.  * be available on a third-party bus interface, for example. Because of this,
  11.  * we must always scan the bus using the original SCSI Manager even if the
  12.  * asynchronous manager is present.
  13.  */
  14. #include "SCSISimpleSample.h"
  15.  
  16. void
  17. DoListSCSIDevices(void)
  18. {
  19.         OSErr                            status;
  20.         unsigned short                    lastHostBus;
  21.         unsigned short                    initiatorID;
  22.         unsigned short                    bus;
  23.         unsigned short                    targetID;
  24.         unsigned short                    LUN;
  25.         DeviceIdent                        scsiDevice;
  26.         SCSIGetVirtualIDInfoPB            scsiGetVirtualIDInfo;
  27.         short                            deviceCount;
  28.         unsigned short                    maxTarget;
  29.         Boolean                            useAsynchManager;
  30.         Str255                            work;
  31.         
  32.         LOG("\pList all SCSI Devices");
  33.         deviceCount = 0;
  34.         /*
  35.          * If we have the asynchronous SCSI Manager, find out how many busses
  36.          * are present on this system. If not, force a "single bus" scan, since 
  37.          * DoSCSICommandWithSense ignores the hostBus information if it is
  38.          * forced into "old-style" calls.
  39.          */
  40.         if (gEnableNewSCSIManager)
  41.             status = SCSIGetHighHostBusAdaptor(&lastHostBus);
  42.         else {
  43.             status = noErr;
  44.             lastHostBus = 0;                    /* Force one bus only            */
  45.         }
  46.         if (status == noErr) {
  47.             for (bus = 0; bus <= lastHostBus; bus++) {
  48.                 /*
  49.                  * Look at this SCSI bus. This would be a good place to allocate
  50.                  * the SCSIExecIO command block. In this sample, however, it's
  51.                  * allocated on each call to AsyncSCSI, though this is inefficient.
  52.                  * Note that it is possible to have busses with no devices. This
  53.                  * is true for Apple Macintosh models with two busses (such as
  54.                  * the Quadra 950 and PowerMac 8100). Also, if you install a
  55.                  * third-party bus adaptor that supports the asynchronous SCSI
  56.                  * Manager on a machine with two busses, it would be assigned
  57.                  * bus 2 (with busses 0 and 1 referencing the internal system
  58.                  * busses). In this case, a system could have no devices on bus
  59.                  * 0 or 1.
  60.                  */
  61.                 *((long *) &scsiDevice) = 0;
  62.                 scsiDevice.bus = bus;
  63.                 /*
  64.                  * Check whether we can access this scsi device. SCSIBusAPI will
  65.                  * return an error status if this bus is inaccessable (i.e. no bus
  66.                  * or other trouble). If it returns noErr, useAsyncManager will
  67.                  * be TRUE if the asynchronous SCSI Manager is supported for this
  68.                  * bus, and FALSE if it can only be accessed through the original
  69.                  * SCSI Manager. This would indicate that a third-party bus
  70.                  * interface patched the original SCSI Manager traps (i.e.,
  71.                  * patched SCSIGet, SCSISelect, etc).
  72.                  */
  73.                 status = SCSIBusAPI(scsiDevice, &useAsynchManager);
  74.                 if (status == noErr) {
  75.                     if (useAsynchManager)
  76.                         status = SCSIGetInitiatorID(scsiDevice, &initiatorID);
  77.                     else {
  78.                         initiatorID = 7;    /* Asynch manager is disabled        */
  79.                     }
  80.                 }
  81.                 if (status != noErr)
  82.                     continue;
  83.                 /*
  84.                  * SCSIGetInitiatorID returned the bus ID of the Macintosh. This
  85.                  * is almost always seven, but only the SCSI Manager knows for
  86.                  * sure. Note that, by getting the Macintosh bus ID dynamically,
  87.                  * we prepare the code for a future system that permitted more
  88.                  * than one Macintosh on the same SCSI bus.
  89.                  */
  90.                 status = SCSIGetMaxTargetID(scsiDevice, &maxTarget);
  91.                 for (targetID = 0; targetID <= maxTarget; targetID++) {
  92.                     if (targetID != initiatorID) {
  93.                         scsiDevice.targetID = targetID;
  94.                         for (LUN = 0; LUN <= gMaxLogicalUnit; LUN++) {
  95.                             /*
  96.                              * Try to send a command to this LUN. If it fails,
  97.                              * don't try for higher-valued LUNs.
  98.                              * SCSICheckForDevicePresent looks, carefully, at the
  99.                              * returned error to distinguish between missing
  100.                              * devices and devices that are present, but unable to
  101.                              * respond, such as CD-ROM players with no disk
  102.                              * inserted. This call to SCSICheckForDevicePresent
  103.                              * will use the asynchronous SCSI Manager if it can.
  104.                              *
  105.                              * Note that, if the asynchronous manager is not
  106.                              * available, we can still check for non-zero LUNs by
  107.                              * using the old method of stuffing the LUN into the
  108.                              * command block, however this is not supported in
  109.                              * this example.
  110.                              */
  111.                             scsiDevice.LUN = LUN;
  112.                             if (SCSICheckForDevicePresent(
  113.                                         scsiDevice, useAsynchManager) == FALSE)
  114.                                 break;                    /* Don't look for LUNs    */
  115.                             else {
  116.                                 ++deviceCount;            /* Found a device        */
  117.                                 DoGetDriveInfo(scsiDevice, TRUE, useAsynchManager);
  118.                             }                            /* Check status            */
  119.                         }                                /* LUN loop                */
  120.                     }                                    /* Not the initiator id    */
  121.                 }                                        /* Target loop            */
  122.             }                                            /* Bus loop                */
  123.             /*
  124.              * Now, we need to look at the hard-wired SCSI drive addresses and
  125.              * check whether a third-party hardware interface that does not use
  126.              * the asynchronous SCSI Manager recognizes this address. If
  127.              * gEnableNewSCSIManager is FALSE, the above loop called the original
  128.              * SCSI Manager, so we don't have to try it again. In this sequence,
  129.              * we hard-wire the initiator ID to seven, as there is no supported
  130.              * way to determine it from the SCSI Manager or operating system.
  131.              */
  132.             if (gEnableNewSCSIManager) {
  133.                 scsiDevice.bus = 0;
  134.                 for (targetID = 0; targetID <= 6; targetID++) {
  135.                      CLEAR(scsiGetVirtualIDInfo);
  136.                      scsiGetVirtualIDInfo.scsiPBLength = sizeof scsiGetVirtualIDInfo;
  137.                      scsiGetVirtualIDInfo.scsiOldCallID = targetID;
  138.                      status = SCSIAction((SCSI_PB *) &scsiGetVirtualIDInfo);
  139.                      if (status != noErr) {
  140.                          /*
  141.                           * The asynchronous SCSI Manager does not know about this
  142.                           * target ID. Check whether it exists (forcing the request
  143.                           * to use the original SCSI Manager).
  144.                           */
  145.                          scsiDevice.targetID = targetID;
  146.                          for (LUN = 0; LUN <= gMaxLogicalUnit; LUN++) {
  147.                              scsiDevice.LUN = LUN;
  148.                             if (SCSICheckForDevicePresent(scsiDevice, FALSE) == FALSE)
  149.                                 break;                    /* Don't look for LUNs    */
  150.                             else {
  151.                                 ++deviceCount;            /* Found a device        */
  152.                                 DoGetDriveInfo(scsiDevice, TRUE, FALSE);
  153.                             }                            /* Check status            */
  154.                         }
  155.                     }
  156.                 }
  157.             }
  158.         }                                                /* Found a host adaptor    */
  159.         NumToString(deviceCount, work);
  160.         AppendPascalString(work, "\p SCSI Devices");
  161.         LOG(work);
  162. }        
  163.